#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>

#include "debugcmd.h"

#define SOCKET_MSG_MAXLEN               256
#define SOCKET_FILE                     "/tmp/socket_dcmd"
#define SOCKET_LISTEN_MAXNUM            5
#define DEBUGCMD_JSON_FILE              "/tmp/cmd.json"

int debugcmd_register(void);

int main()
{
    int ret = 0;
    int client_sockfd = 0;
    int server_sockfd = 0;
    char *retmsg = NULL;
    char mesg[SOCKET_MSG_MAXLEN];
    struct sockaddr_un client_addr;
    struct sockaddr_un server_addr;
    socklen_t len = sizeof(client_addr);
    ssize_t cnt = 0;

    ret = debugcmd_init();
    if(ret)
    {
        printf("err: debugcmd_init\n");
        return -1;
    }

    ret = debugcmd_register();
    if(ret)
    {
        printf("err: debugcmd_register\n");
        return -1;
    }

    ret = debugcmd_export(DEBUGCMD_JSON_FILE);
    if(ret)
    {
        printf("err: debugcmd_execute\n");
        return -1;
    }

    //ret = debugcmd_execute(char * str);

    /* delete the socket file */
    unlink(SOCKET_FILE);

    /* create a socket */
    server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if(-1 == server_sockfd)
    {
        printf("err: socket\n");
        exit(1);
    }

    /* bind with the local file */
    server_addr.sun_family = AF_UNIX;
    strcpy(server_addr.sun_path, SOCKET_FILE);
    ret = bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if(-1 == ret)
    {
        printf("err: bind\n");
        exit(1);
    }

    /* listen */
    ret = listen(server_sockfd, SOCKET_LISTEN_MAXNUM);
    if(-1 == ret)
    {
        printf("err: listen\n");
        exit(1);
    }

    while(1)
    {
        /* waiting for client connection */
        client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &len);
        if(-1 == ret)
        {
            printf("err: accept\n");
            exit(1);
        }

        /* exchange data */
        memset(mesg, 0, sizeof(mesg));
        cnt = read(client_sockfd, &mesg, SOCKET_MSG_MAXLEN);
        if(0 >= cnt)
        {
            printf("err: read\n");
            exit(1);
        }

        /* show input string */
        //printf("input string is: \"%s\", cnt = %ld\r\n", mesg, cnt);

        /* try to execute */
        ret = debugcmd_execute(mesg);
        retmsg = ret ? "NG" : "OK";
        send(client_sockfd, retmsg, strlen(retmsg) + sizeof(char), 0);

        /* close the socket */
        ret = close(client_sockfd);
        if(-1 == ret)
        {
            printf("err: close\n");
            exit(1);
        }
    }

    return 0;
}

/*---------------------------------------------------------------------------------------------------------------------
 * 命令回调函数定义
 *-------------------------------------------------------------------------------------------------------------------*/

/**
 * @brief i2c 读函数
 * @retval 错误码
 */
int MAZ_CMD_i2c_read(void *cmd, char *param)
{
    uint32_t slave;
    uint32_t reg;

    sscanf(param, "0x%x 0x%x", &slave, &reg);

    printf("i2c read cmd is running\r\n");
    printf("slave = 0x%02x\r\n", slave);
    printf("reg   = 0x%02x\r\n", reg);

    return 0;
}

/**
 * @brief i2c 写函数
 * @retval 错误码
 */
int MAZ_CMD_i2c_write(void *cmd, char *param)
{
    uint32_t slave;
    uint32_t reg;
    uint32_t val;

    sscanf(param, "0x%x 0x%x 0x%x", &slave, &reg, &val);

    printf("i2c write cmd is running\r\n");
    printf("slave = 0x%02x\r\n", slave);
    printf("reg   = 0x%02x\r\n", reg);
    printf("val   = 0x%02x\r\n", val);

    return 0;
}

/**
 * @brief i2c dump函数
 * @retval 错误码
 */
int MAZ_CMD_i2c_dump(void *cmd, char *param)
{
    uint32_t slave;

    sscanf(param, "0x%x", &slave);

    printf("i2c dump cmd is running\r\n");
    printf("slave = 0x%02x\r\n", slave);

    return 0;
}

/**
 * @brief 系统推出函数
 * @retval 错误码
 */
int MAZ_CMD_exit(void *cmd, char *param)
{
    printf("exit.\r\n");
    system("stty icanon echo");
    exit(0);
    return 0;
}

/**
 * @brief 打印单个字符
 * @retval none
 */
void __io_putchar(char c)
{
    printf("%c", c);
    fflush(stdout);
}

/**
 * @brief 清屏函数
 * @retval 错误码
 */
int MAZ_CMD_clear(void *cmd, char *param)
{
    /* 基于 VT100 控制码实现清屏动作 */
    __io_putchar('\x1b');
    __io_putchar('[');
    __io_putchar('2');
    __io_putchar('J');
    __io_putchar('\x1b');
    __io_putchar('[');
    __io_putchar('H');
    return 0;
}

DEBUGCMD_MCMD i2c           = {"i2c",       "i2c bus debug command."};
DEBUGCMD_SCMD i2c_read      = {" read",     "i2c read <slave> <reg>.",          MAZ_CMD_i2c_read};
DEBUGCMD_SCMD i2c_write     = {"write ",    "i2c wrtie <slave> <reg> <val>.",   MAZ_CMD_i2c_write};
DEBUGCMD_SCMD i2c_dump      = {"dump",      "i2c dump <slave>.",                MAZ_CMD_i2c_dump};
DEBUGCMD_MCMD sysexit       = {"exit",      "exit",                             MAZ_CMD_exit};
DEBUGCMD_MCMD clear         = {"clear",     "clear",                            MAZ_CMD_clear};

/**
 * @brief 注册命令函数
 * @retval 错误码
 */
int debugcmd_register(void)
{
    debugcmd_mcmd_register(&i2c);
    debugcmd_scmd_register(&i2c, &i2c_read);
    debugcmd_scmd_register(&i2c, &i2c_write);
    debugcmd_scmd_register(&i2c, &i2c_dump);
    debugcmd_mcmd_register(&sysexit);
    debugcmd_mcmd_register(&clear);
    return 0;
}
